/**
 * 命令依赖管理器
 * 
 * 职责：
 * 1. 管理命令之间的依赖关系
 * 2. 使用拓扑排序确定执行顺序
 * 3. 检测循环依赖
 * 4. 支持命令分组和批量依赖
 * 
 * @author AI Assistant
 * @date 2025-11-26
 */

import { ICommand, CommandType } from "./CommandQueue";
import { Log } from "../../../core/logger/LoggerGlobal";

/**
 * 依赖关系
 */
export interface IDependency {
    /** 依赖的命令 ID */
    commandId: string;
    
    /** 依赖类型 */
    type: DependencyType;
}

/**
 * 依赖类型
 */
export enum DependencyType {
    /** 强依赖：必须等待依赖完成 */
    STRONG = 'strong',
    
    /** 弱依赖：如果依赖存在则等待，不存在则忽略 */
    WEAK = 'weak',
    
    /** 顺序依赖：保证在依赖之后执行，但不等待完成 */
    ORDER = 'order'
}

/**
 * 依赖图节点
 */
interface DependencyNode {
    /** 命令对象 */
    command: ICommand;
    
    /** 依赖的命令 ID 列表 */
    dependencies: string[];
    
    /** 入度（有多少命令依赖它） */
    inDegree: number;
    
    /** 出度（它依赖多少命令） */
    outDegree: number;
    
    /** 是否已访问（用于循环检测） */
    visited: boolean;
    
    /** 是否在当前路径中（用于循环检测） */
    inPath: boolean;
}

/**
 * 命令依赖管理器
 */
export class CommandDependencyManager {
    /** 依赖图：commandId -> DependencyNode */
    private dependencyGraph: Map<string, DependencyNode> = new Map();
    
    /** 依赖关系：commandId -> 依赖它的命令列表 */
    private dependents: Map<string, Set<string>> = new Map();
    
    /** 命令分组：groupName -> commandId[] */
    private commandGroups: Map<string, string[]> = new Map();
    
    /** 统计信息 */
    private stats = {
        totalNodes: 0,
        totalEdges: 0,
        circularDependencies: 0,
        maxDepth: 0
    };
    
    /**
     * 添加命令到依赖图
     * @param command 命令对象
     * @param dependencies 依赖的命令 ID 列表
     */
    addCommand(command: ICommand, dependencies: string[] = []): void {
        // 创建节点
        const node: DependencyNode = {
            command,
            dependencies: [...dependencies],
            inDegree: 0,
            outDegree: dependencies.length,
            visited: false,
            inPath: false
        };
        
        this.dependencyGraph.set(command.id, node);
        this.stats.totalNodes++;
        
        // 更新依赖关系
        for (const depId of dependencies) {
            // 更新被依赖命令的入度
            const depNode = this.dependencyGraph.get(depId);
            if (depNode) {
                depNode.inDegree++;
            }
            
            // 记录反向依赖关系
            if (!this.dependents.has(depId)) {
                this.dependents.set(depId, new Set());
            }
            this.dependents.get(depId)!.add(command.id);
            
            this.stats.totalEdges++;
        }
    }
    
    /**
     * 移除命令
     * @param commandId 命令 ID
     */
    removeCommand(commandId: string): void {
        const node = this.dependencyGraph.get(commandId);
        if (!node) return;
        
        // 移除依赖关系
        for (const depId of node.dependencies) {
            const depNode = this.dependencyGraph.get(depId);
            if (depNode) {
                depNode.inDegree--;
            }
            
            const deps = this.dependents.get(depId);
            if (deps) {
                deps.delete(commandId);
                if (deps.size === 0) {
                    this.dependents.delete(depId);
                }
            }
            
            this.stats.totalEdges--;
        }
        
        // 移除被依赖关系
        const deps = this.dependents.get(commandId);
        if (deps) {
            for (const depId of deps) {
                const depNode = this.dependencyGraph.get(depId);
                if (depNode) {
                    const index = depNode.dependencies.indexOf(commandId);
                    if (index !== -1) {
                        depNode.dependencies.splice(index, 1);
                        depNode.outDegree--;
                    }
                }
            }
            this.dependents.delete(commandId);
        }
        
        // 移除节点
        this.dependencyGraph.delete(commandId);
        this.stats.totalNodes--;
    }
    
    /**
     * 添加依赖关系
     * @param commandId 命令 ID
     * @param dependencyId 依赖的命令 ID
     */
    addDependency(commandId: string, dependencyId: string): boolean {
        const node = this.dependencyGraph.get(commandId);
        const depNode = this.dependencyGraph.get(dependencyId);
        
        if (!node || !depNode) {
            Log.ecs.warn('命令不存在', { commandId, dependencyId });
            return false;
        }
        
        // 检查是否已存在
        if (node.dependencies.includes(dependencyId)) {
            return true;
        }
        
        // 检查是否会造成循环依赖
        if (this.wouldCreateCycle(commandId, dependencyId)) {
            Log.ecs.error('添加依赖会造成循环', {
                commandId,
                dependencyId
            });
            this.stats.circularDependencies++;
            return false;
        }
        
        // 添加依赖
        node.dependencies.push(dependencyId);
        node.outDegree++;
        depNode.inDegree++;
        
        // 更新反向依赖
        if (!this.dependents.has(dependencyId)) {
            this.dependents.set(dependencyId, new Set());
        }
        this.dependents.get(dependencyId)!.add(commandId);
        
        this.stats.totalEdges++;
        return true;
    }
    
    /**
     * 检查是否会造成循环依赖
     * @param from 起始命令 ID
     * @param to 目标命令 ID
     */
    private wouldCreateCycle(from: string, to: string): boolean {
        // 从 to 开始 DFS，看能否到达 from
        const visited = new Set<string>();
        const stack: string[] = [to];
        
        while (stack.length > 0) {
            const current = stack.pop()!;
            
            if (current === from) {
                return true; // 找到循环
            }
            
            if (visited.has(current)) {
                continue;
            }
            
            visited.add(current);
            
            const node = this.dependencyGraph.get(current);
            if (node) {
                stack.push(...node.dependencies);
            }
        }
        
        return false;
    }
    
    /**
     * 拓扑排序
     * @returns 排序后的命令列表，如果有循环依赖则返回 null
     */
    topologicalSort(): ICommand[] | null {
        if (this.dependencyGraph.size === 0) {
            return [];
        }
        
        // 复制入度信息
        const inDegrees = new Map<string, number>();
        for (const [id, node] of this.dependencyGraph) {
            inDegrees.set(id, node.inDegree);
        }
        
        // 找出所有入度为 0 的节点
        const queue: string[] = [];
        for (const [id, degree] of inDegrees) {
            if (degree === 0) {
                queue.push(id);
            }
        }
        
        const result: ICommand[] = [];
        let maxDepth = 0;
        
        // Kahn 算法
        while (queue.length > 0) {
            const currentId = queue.shift()!;
            const node = this.dependencyGraph.get(currentId)!;
            
            result.push(node.command);
            maxDepth = Math.max(maxDepth, result.length);
            
            // 处理所有依赖当前节点的命令
            const deps = this.dependents.get(currentId);
            if (deps) {
                for (const depId of deps) {
                    const degree = inDegrees.get(depId)! - 1;
                    inDegrees.set(depId, degree);
                    
                    if (degree === 0) {
                        queue.push(depId);
                    }
                }
            }
        }
        
        // 检查是否所有节点都被处理
        if (result.length !== this.dependencyGraph.size) {
            Log.ecs.error('检测到循环依赖！');
            this.stats.circularDependencies++;
            
            // 找出循环依赖的节点
            const cycleNodes: string[] = [];
            for (const [id, degree] of inDegrees) {
                if (degree > 0) {
                    cycleNodes.push(id);
                }
            }
            
            Log.ecs.error('循环依赖的节点', { cycleNodes });
            return null;
        }
        
        this.stats.maxDepth = maxDepth;
        return result;
    }
    
    /**
     * 检测循环依赖
     * @returns 循环依赖的路径列表
     */
    detectCycles(): string[][] {
        const cycles: string[][] = [];
        
        // 重置访问状态
        for (const node of this.dependencyGraph.values()) {
            node.visited = false;
            node.inPath = false;
        }
        
        // DFS 检测循环
        const dfs = (nodeId: string, path: string[]): void => {
            const node = this.dependencyGraph.get(nodeId);
            if (!node) return;
            
            if (node.inPath) {
                // 找到循环
                const cycleStart = path.indexOf(nodeId);
                if (cycleStart !== -1) {
                    cycles.push(path.slice(cycleStart).concat(nodeId));
                }
                return;
            }
            
            if (node.visited) return;
            
            node.visited = true;
            node.inPath = true;
            path.push(nodeId);
            
            for (const depId of node.dependencies) {
                dfs(depId, path);
            }
            
            path.pop();
            node.inPath = false;
        };
        
        for (const nodeId of this.dependencyGraph.keys()) {
            const node = this.dependencyGraph.get(nodeId)!;
            if (!node.visited) {
                dfs(nodeId, []);
            }
        }
        
        return cycles;
    }
    
    /**
     * 创建命令分组
     * @param groupName 分组名称
     * @param commandIds 命令 ID 列表
     */
    createGroup(groupName: string, commandIds: string[]): void {
        this.commandGroups.set(groupName, [...commandIds]);
    }
    
    /**
     * 添加分组依赖
     * @param groupName 分组名称
     * @param dependencyGroupName 依赖的分组名称
     */
    addGroupDependency(groupName: string, dependencyGroupName: string): boolean {
        const group = this.commandGroups.get(groupName);
        const depGroup = this.commandGroups.get(dependencyGroupName);
        
        if (!group || !depGroup) {
            Log.ecs.warn('命令分组不存在', {
                groupName,
                dependencyGroupName
            });
            return false;
        }
        
        // 为分组中的每个命令添加依赖
        let success = true;
        for (const cmdId of group) {
            for (const depId of depGroup) {
                if (!this.addDependency(cmdId, depId)) {
                    success = false;
                }
            }
        }
        
        return success;
    }
    
    /**
     * 获取命令的所有依赖（递归）
     * @param commandId 命令 ID
     * @returns 所有依赖的命令 ID 列表
     */
    getAllDependencies(commandId: string): string[] {
        const result = new Set<string>();
        const visited = new Set<string>();
        
        const dfs = (id: string): void => {
            if (visited.has(id)) return;
            visited.add(id);
            
            const node = this.dependencyGraph.get(id);
            if (!node) return;
            
            for (const depId of node.dependencies) {
                result.add(depId);
                dfs(depId);
            }
        };
        
        dfs(commandId);
        return Array.from(result);
    }
    
    /**
     * 获取依赖当前命令的所有命令（递归）
     * @param commandId 命令 ID
     * @returns 所有依赖当前命令的命令 ID 列表
     */
    getAllDependents(commandId: string): string[] {
        const result = new Set<string>();
        const visited = new Set<string>();
        
        const dfs = (id: string): void => {
            if (visited.has(id)) return;
            visited.add(id);
            
            const deps = this.dependents.get(id);
            if (!deps) return;
            
            for (const depId of deps) {
                result.add(depId);
                dfs(depId);
            }
        };
        
        dfs(commandId);
        return Array.from(result);
    }
    
    /**
     * 清空依赖图
     */
    clear(): void {
        this.dependencyGraph.clear();
        this.dependents.clear();
        this.commandGroups.clear();
        
        this.stats = {
            totalNodes: 0,
            totalEdges: 0,
            circularDependencies: 0,
            maxDepth: 0
        };
    }
    
    /**
     * 获取统计信息
     */
    getStats() {
        return {
            ...this.stats,
            groups: this.commandGroups.size
        };
    }
    
    /**
     * 打印依赖图（调试用）
     */
    printGraph(): void {
        Log.styled('━'.repeat(60), 'separator');
        Log.styled('🔗 命令依赖图', 'title');
        Log.styled('━'.repeat(60), 'separator');
        
        Log.performance.info(`节点数: ${this.stats.totalNodes}`);
        Log.performance.info(`边数: ${this.stats.totalEdges}`);
        Log.performance.info(`最大深度: ${this.stats.maxDepth}`);
        Log.performance.info(`循环依赖数: ${this.stats.circularDependencies}`);
        
        Log.styled('📋 依赖关系', 'large');
        
        for (const [id, node] of this.dependencyGraph) {
            Log.ecs.debug(`  ${id} (入度: ${node.inDegree}, 出度: ${node.outDegree})`);
            if (node.dependencies.length > 0) {
                Log.ecs.debug(`    依赖: ${node.dependencies.join(', ')}`);
            }
            
            const deps = this.dependents.get(id);
            if (deps && deps.size > 0) {
                Log.ecs.debug(`    被依赖: ${Array.from(deps).join(', ')}`);
            }
        }
        
        Log.styled('━'.repeat(60), 'separator');
    }
    
    /**
     * 可视化依赖图（Mermaid 格式）
     */
    visualize(): string {
        let mermaid = 'graph TD\n';
        
        for (const [id, node] of this.dependencyGraph) {
            const shortId = id.substring(0, 8);
            const cmdType = node.command.type;
            
            mermaid += `  ${shortId}[${cmdType}]\n`;
            
            for (const depId of node.dependencies) {
                const shortDepId = depId.substring(0, 8);
                mermaid += `  ${shortDepId} --> ${shortId}\n`;
            }
        }
        
        return mermaid;
    }
}

/**
 * 导出依赖管理器单例
 */
export const commandDependencyManager = new CommandDependencyManager();

